package com.gitee.apanlh.util.reflection;

import com.gitee.apanlh.util.base.MapUtils;
import com.gitee.apanlh.util.base.builder.MapBuilder;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;

/**	
 * 	基本数据类型
 * 	
 * 	@author Pan
 */
public class ClassTypeUtils {
	
	/**
	 * 	构造函数
	 * 
	 * 	@author Pan
	 */
	private ClassTypeUtils() {
		//	不允许外部实例
		super();
	}
	
	/**
	 * 	基本数据类型
	 * 	<br>Key   = 包装数据类型
	 * 	<br>Value = 原始数据类型
	 */
	protected static final Map<Class<?>, Class<?>> BASIC_DATA_TYPE_MAP = new MapBuilder.Builder<Class<?>, Class<?>>(MapUtils.newHashMap(8))
		.put(Byte		.class, 		byte	 .class)
		.put(Short		.class, 		short	 .class)
		.put(Integer	.class, 		int		 .class)
		.put(Long		.class, 		long	 .class)
		.put(Float		.class, 		float	 .class)
		.put(Double		.class, 		double	 .class)
		.put(Boolean	.class, 		boolean	 .class)
		.put(Character	.class, 		char	 .class)
	.build();
	
	/**
	 * 	包装数据类型
	 * 	<br>Key   = 原始数据类型
	 * 	<br>Value = 包装数据类型
	 */
	protected static final Map<Class<?>, Class<?>> WRAPPER_DATA_TYPE_MAP = new MapBuilder.Builder<Class<?>, Class<?>>(MapUtils.newHashMap(8))
		.put(byte		.class, 		Byte	 .class)
		.put(short		.class, 		Short	 .class)
		.put(int		.class, 		Integer	 .class)
		.put(long		.class, 		Long	 .class)
		.put(float		.class, 		Float	 .class)
		.put(double		.class, 		Double	 .class)
		.put(boolean	.class, 		Boolean	 .class)
		.put(char		.class, 		Character.class)
	.build();
	
	/**	
	 * 	将包装类型转化成基本数据类型
	 * 	<br>如果已经是基本数据类型则返回原有Class
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz 类
	 * 	@return Class
	 */
	public static Class<?> convertBasicType(Class<?> clazz) {
		//	验证是否是原始类型
		if (clazz == null || isPrimitive(clazz)) {
			return clazz;
		}
		
		Class<?> value = BASIC_DATA_TYPE_MAP.get(clazz);
		return value == null ? clazz : value;
	}

	/**
	 * 	将基本数据类型转化成包装类型
	 * 	<br>如果已经是包装类型则返回原有Class
	 *
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	Class
	 */
	public static Class<?> convertWrapperType(Class<?> clazz) {
		//	验证是否是包装类型
		if (clazz == null || !isPrimitive(clazz)) {
			return clazz;
		}

		Class<?> value = WRAPPER_DATA_TYPE_MAP.get(clazz);
		return value == null ? clazz : value;
	}
	
	/**
	 * 	是否属于数据类型
	 * 	<br>包含原始类型，包装类型
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	boolean
	 */
	public static boolean isBasicDataType(Class<?> clazz) {
		if (clazz == null) {
			return false;
		}
		return !(BASIC_DATA_TYPE_MAP.get(clazz) == null && WRAPPER_DATA_TYPE_MAP.get(clazz) == null);
	}
	
	/**	
	 * 	是否属于数据类型
	 * 	<br>包含原始类型，包装类型
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	boolean
	 */
	public static boolean isBasicDataTypes(Class<?>... clazz) {
		for (int i = 0, len = clazz.length; i < len; i++) {
			if (!isBasicDataType(clazz[i])) {
				return false;
			}
		}
		return true;
	}
	
	/**	
	 * 	是否为String类型
	 * 	
	 * 	@author Pan
	 * 	@param 	obj	对象
	 * 	@return	boolean
	 */
	public static boolean isString(Object obj) {
		if (obj == null) {
			return false;
		}
		return isString(obj.getClass());
	}
	
	/**	
	 * 	是否为String类型
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	boolean
	 */
	public static boolean isString(Class<?> clazz) {
		return "String".equals(ClassUtils.getSimpleName(clazz));
	}
	
	/**	
	 * 	验证是数组
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	boolean
	 */
	public static boolean isArray(Class<?> clazz) {
		return clazz.isArray();
	}
	
	/**	
	 * 	验证是数组
	 * 	
	 * 	@author Pan
	 * 	@param 	obj	对象
	 * 	@return	boolean
	 */
	public static boolean isArray(Object obj) {
		if (obj == null) {
			return false;
		}
		return isArray(obj.getClass());
	}
	
	/**	
	 * 	是否为byte[]
	 * 	
	 * 	@author Pan
	 * 	@param 	obj	对象
	 * 	@return	boolean
	 */
	public static boolean isArrayByte(Object obj) {
		if (obj == null) {
			return false;
		}
		return isArrayByte(obj.getClass());
	}
	
	/**	
	 * 	是否为byte[]
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	boolean
	 */
	public static boolean isArrayByte(Class<?> clazz) {
		return isAssignableFrom(clazz, byte[].class);
	}
	
	/**	
	 * 	是否为short[]
	 * 	
	 * 	@author Pan
	 * 	@param 	obj	对象
	 * 	@return	boolean
	 */
	public static boolean isArrayShort(Object obj) {
		if (obj == null) {
			return false;
		}
		return isArrayShort(obj.getClass());
	}
	
	/**	
	 * 	是否为short[]
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	boolean
	 */
	public static boolean isArrayShort(Class<?> clazz) {
		return isAssignableFrom(clazz, short[].class);
	}
	
	/**	
	 * 	是否为int[]
	 * 	
	 * 	@author Pan
	 * 	@param 	obj	对象
	 * 	@return	boolean
	 */
	public static boolean isArrayInt(Object obj) {
		if (obj == null) {
			return false;
		}
		return isArrayInt(obj.getClass());
	}
	
	/**	
	 * 	是否为int[]
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	boolean
	 */
	public static boolean isArrayInt(Class<?> clazz) {
		return isAssignableFrom(clazz, int[].class);
	}
	
	/**	
	 * 	是否为long[]
	 * 	
	 * 	@author Pan
	 * 	@param 	obj	对象
	 * 	@return	boolean
	 */
	public static boolean isArrayLong(Object obj) {
		if (obj == null) {
			return false;
		}
		return isArrayLong(obj.getClass());
	}
	
	/**	
	 * 	是否为long[]
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	boolean
	 */
	public static boolean isArrayLong(Class<?> clazz) {
		return isAssignableFrom(clazz, long[].class);
	}
	
	/**	
	 * 	是否为float[]
	 * 	
	 * 	@author Pan
	 * 	@param 	obj	对象 对象
	 * 	@return	boolean
	 */
	public static boolean isArrayFloat(Object obj) {
		if (obj == null) {
			return false;
		}
		return isArrayFloat(obj.getClass());
	}
	
	/**	
	 * 	是否为float[]
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	boolean
	 */
	public static boolean isArrayFloat(Class<?> clazz) {
		return isAssignableFrom(clazz, float[].class);
	}
	
	/**	
	 * 	是否为double[]
	 * 	
	 * 	@author Pan
	 * 	@param 	obj	对象
	 * 	@return	boolean
	 */
	public static boolean isArrayDouble(Object obj) {
		if (obj == null) {
			return false;
		}
		return isArrayDouble(obj.getClass());
	}
	
	/**	
	 * 	是否为double[]
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	boolean
	 */
	public static boolean isArrayDouble(Class<?> clazz) {
		return isAssignableFrom(clazz, double[].class);
	}
	
	/**	
	 * 	是否为boolean[]
	 * 	
	 * 	@author Pan
	 * 	@param 	obj	对象
	 * 	@return	boolean
	 */
	public static boolean isArrayBoolean(Object obj) {
		if (obj == null) {
			return false;
		}
		return isArrayBoolean(obj.getClass());
	}
	
	/**	
	 * 	是否为boolean[]
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	boolean
	 */
	public static boolean isArrayBoolean(Class<?> clazz) {
		return isAssignableFrom(clazz, boolean[].class);
	}

	/**
	 * 	是否为char[]
	 *
	 * 	@author Pan
	 * 	@param 	obj	对象
	 * 	@return	boolean
	 */
	public static boolean isArrayChar(Object obj) {
		if (obj == null) {
			return false;
		}
		return isArrayChar(obj.getClass());
	}

	/**	
	 * 	是否为char[]
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	boolean
	 */
	public static boolean isArrayChar(Class<?> clazz) {
		return isAssignableFrom(clazz, char[].class);
	}
	
	/**
	 * 	是否为文件
	 * 	
	 * 	@author Pan
	 * 	@param 	obj	对象
	 * 	@return	boolean
	 */
	public static boolean isFile(Object obj) {
		return obj instanceof File;
	}
	
	/**
	 * 	是否为文件输入流
	 * 	
	 * 	@author Pan
	 * 	@param 	obj	对象
	 * 	@return	boolean
	 */
	public static boolean isFileInputStream(Object obj) {
		return obj instanceof FileInputStream;
	}
	
	/**
	 * 	是否为输入流
	 * 	
	 * 	@author Pan
	 * 	@param 	obj	对象
	 * 	@return	boolean
	 */
	public static boolean isInputStream(Object obj) {
		return obj instanceof InputStream;
	}
	
	/**
	 * 	是否为输出流
	 * 	
	 * 	@author Pan
	 * 	@param 	obj	对象
	 * 	@return	boolean
	 */
	public static boolean isOutputStream(Object obj) {
		return obj instanceof OutputStream;
	}

	/**
	 * 	是否为Map
	 *
	 * 	@author Pan
	 * 	@param 	obj	对象
	 * 	@return	boolean
	 */
	public static boolean isMap(Object obj) {
		return obj instanceof Map;
	}

	/**
	 * 	是否为WeakHashMap
	 * 	
	 * 	@author Pan
	 * 	@param 	obj	对象
	 * 	@return	boolean
	 */
	public static boolean isWeakHashMap(Object obj) {
		return obj instanceof WeakHashMap;
	}
	
	/**
	 * 	是否为ConcurrentHashMap
	 * 	
	 * 	@author Pan
	 * 	@param 	obj	对象
	 * 	@return	boolean
	 */
	public static boolean isConcurrentHashMap(Object obj) {
		return obj instanceof ConcurrentHashMap;
	}
	
	/**
	 * 	是否为Collection
	 * 	
	 * 	@author Pan
	 * 	@param 	obj	对象
	 * 	@return	boolean
	 */
	public static boolean isCollection(Object obj) {
		return obj instanceof Collection;
	}
	
	/**	
	 * 	验证是否是接口
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	boolean
	 */
	public static boolean isInterface(Class<?> clazz) {
		return clazz.isInterface();
	}
	
	/**	
	 * 	验证是否是接口
	 * 	
	 * 	@author Pan
	 * 	@param 	obj	对象
	 * 	@return	boolean
	 */
	public static boolean isInterface(Object obj) {
		if (obj == null) {
			return false;
		}
		return isInterface(obj.getClass());
	}
	
	/**	
	 * 	验证是基本类型
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz	类
	 * 	@return	boolean
	 */
	public static boolean isPrimitive(Class<?> clazz) {
		return clazz.isPrimitive();
	}
	
	/**	
	 * 	验证基本类型是否一致
	 * 	
	 * 	@author Pan
	 * 	@param 	clazz1	类1
	 * 	@param 	clazz2	类2
	 * 	@return	boolean
	 */
	public static boolean isAssignableFrom(Class<?> clazz1, Class<?> clazz2) {
		return clazz1.isAssignableFrom(clazz2);
	}
	
}
